home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / programming / other / jikes / src / zip.cpp < prev    next >
C/C++ Source or Header  |  1999-05-14  |  13KB  |  399 lines

  1. // $Id: zip.cpp,v 1.3 1999/01/25 20:00:32 shields Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10. #include "config.h"
  11. #include <assert.h>
  12. #include <iostream.h>
  13. #include <string.h>
  14. #include "control.h"
  15. #include "zip.h"
  16. #include "symbol.h"
  17.  
  18. //************************************************************************************************
  19. //
  20. // The ZipFile methods follow
  21. //
  22. //************************************************************************************************
  23. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  24.     int (*ZipFile::uncompress_file[10]) (FILE *, char *, long) =
  25.     {
  26.         UncompressFile0,
  27.         UncompressFile1,
  28.         UncompressFile2,
  29.         UncompressFile3,
  30.         UncompressFile4,
  31.         UncompressFile5,
  32.         UncompressFile6,
  33.         UncompressFile7,
  34.         UncompressFile8,
  35.         UncompressFile9
  36.     };
  37.  
  38.     inline u1 ZipFile::GetU1()
  39.     {
  40.         return getc(zipfile);
  41.     }
  42.  
  43.     inline void ZipFile::Skip(u4 length)
  44.     {
  45.         for (u4 i = 0; i < length; i++)
  46.              getc(zipfile);
  47.     }
  48.  
  49. #elif defined(WIN32_FILE_SYSTEM)
  50.  
  51.     int (*ZipFile::uncompress_file[10]) (char *, char *, long) =
  52.     {
  53.         UncompressFile0,
  54.         UncompressFile1,
  55.         UncompressFile2,
  56.         UncompressFile3,
  57.         UncompressFile4,
  58.         UncompressFile5,
  59.         UncompressFile6,
  60.         UncompressFile7,
  61.         UncompressFile8,
  62.         UncompressFile9
  63.     };
  64.  
  65.     inline u1 ZipFile::GetU1()
  66.     {
  67.         return *file_buffer++;
  68.     }
  69.  
  70.     inline void ZipFile::Skip(u4 length)
  71.     {
  72.         file_buffer += length;
  73.     }
  74.  
  75. #endif
  76.  
  77.  
  78. inline u2 ZipFile::GetU2()
  79. {
  80.     u4 val = GetU1();
  81.     val |= (((u4) GetU1()) << 8);
  82.  
  83.     return val;
  84. }
  85.  
  86.  
  87. inline u4 ZipFile::GetU4()
  88. {
  89.     u4 val = GetU1();
  90.     val |= (((u4) GetU1()) << 8);
  91.     val |= (((u4) GetU1()) << 16);
  92.     val |= (((u4) GetU1()) << 24);
  93.  
  94.     return val;
  95. }
  96.  
  97.  
  98. ZipFile::ZipFile(FileSymbol *file_symbol) : buffer(NULL)
  99. {
  100.     Zip *zip = file_symbol -> Zipfile();
  101.  
  102. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  103.     zipfile = zip -> zipfile;
  104.     int rc = fseek(zipfile, file_symbol -> offset, SEEK_SET);
  105.     assert(rc == 0);
  106. #elif defined(WIN32_FILE_SYSTEM)
  107.     file_buffer = &zip -> zipbuffer[file_symbol -> offset];
  108. #endif
  109.     
  110.     Skip(8); // u4 magic                     = GetU4();
  111.              // u2 version_needed_to_extract = GetU2();
  112.              // u2 general_purpose_bits      = GetU2();
  113.     u2 compression_method                    = GetU2();
  114.     Skip(16); // u2 time                     = GetU2();
  115.               // u2 date                     = GetU2();
  116.               // u4 crc32                    = GetU4();
  117.               // u4 compressed_size          = GetU4();
  118.               // u4 uncompressed_size        = GetU4();
  119.     u2 filename_length                       = GetU2();
  120.     u2 extra_field_length                    = GetU2();
  121.     Skip(filename_length + extra_field_length);
  122.      
  123. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  124.     this -> buffer = new char[file_symbol -> uncompressed_size];
  125.     if (! uncompress_file[compression_method < 9 ? compression_method : 9](zipfile, this -> buffer, file_symbol -> uncompressed_size))
  126.     {
  127.         delete [] this -> buffer;
  128.         this -> buffer = NULL;
  129.     }
  130. #elif defined(WIN32_FILE_SYSTEM)
  131.     if (compression_method > 0)
  132.     {
  133.         this -> buffer = new char[file_symbol -> uncompressed_size];
  134.         if (! uncompress_file[compression_method < 9 ? compression_method : 9](file_buffer,
  135.                                                                                this -> buffer,
  136.                                                                                file_symbol -> uncompressed_size))
  137.         {
  138.             delete [] this -> buffer;
  139.             this -> buffer = NULL;
  140.             this -> file_buffer = NULL;
  141.         }
  142.     }
  143. #endif
  144.  
  145.     return;
  146. }
  147.  
  148.  
  149. ZipFile::~ZipFile()
  150. {
  151.     delete [] buffer;
  152. }
  153.  
  154.  
  155. //************************************************************************************************
  156. //
  157. // The Zip methods follow:
  158. //
  159. //************************************************************************************************
  160. inline u1 Zip::GetU1()
  161. {
  162.     return *buffer_ptr++;
  163. }
  164.  
  165.  
  166. inline u2 Zip::GetU2()
  167. {
  168.     u4 val = GetU1();
  169.     val |= (((u4) GetU1()) << 8);
  170.  
  171.     return val;
  172. }
  173.  
  174.  
  175. inline u4 Zip::GetU4()
  176. {
  177.     u4 val = GetU1();
  178.     val |= (((u4) GetU1()) << 8);
  179.     val |= (((u4) GetU1()) << 16);
  180.     val |= (((u4) GetU1()) << 24);
  181.  
  182.     return val;
  183. }
  184.  
  185.  
  186. inline void Zip::Skip(u4 length)
  187. {
  188.     buffer_ptr += length;
  189. }
  190.  
  191.  
  192. inline DirectorySymbol *Zip::ProcessSubdirectoryEntries(DirectorySymbol *directory_symbol, char *name, int name_length)
  193. {
  194.     wchar_t *directory_name = new wchar_t[name_length];
  195.  
  196.     for (int start = 0, end; start < name_length; start = end + 1)
  197.     {
  198.         end = start;
  199.         for (int i = 0; end < name_length && name[end] != U_SLASH; i++, end++)
  200.              directory_name[i] = name[end];
  201.         NameSymbol *name_symbol = control.FindOrInsertName(directory_name, end - start);
  202.         DirectorySymbol *subdirectory_symbol = directory_symbol -> FindDirectorySymbol(name_symbol);
  203.         if (! subdirectory_symbol)
  204.             subdirectory_symbol = directory_symbol -> InsertDirectorySymbol(name_symbol);
  205.         directory_symbol = subdirectory_symbol;
  206.     }
  207.  
  208.     delete [] directory_name;
  209.  
  210.     return directory_symbol;
  211. }
  212.  
  213.  
  214. inline NameSymbol *Zip::ProcessFilename(char *name, int name_length)
  215. {
  216.     wchar_t *input_filename = new wchar_t[name_length];
  217.     for (int i = 0; i < name_length; i++)
  218.         input_filename[i] = name[i];
  219.     NameSymbol *name_symbol = control.FindOrInsertName(input_filename, name_length);
  220.  
  221.     delete [] input_filename;
  222.  
  223.     return name_symbol;
  224. }
  225.  
  226.  
  227. inline void Zip::ProcessDirectoryEntry(DirectorySymbol *directory_symbol)
  228. {
  229.     Skip(8); // u2 version_made_by           = GetU2();
  230.              // u2 version_needed_to_extract = GetU2();
  231.              // u2 general_purpose_bits      = GetU2();
  232.              // u2 compression_method        = GetU2();
  233.     u2 last_mod_file_time                    = GetU2();
  234.     u2 last_mod_file_date                    = GetU2();
  235.     Skip(4); // u4 crc32                     = GetU4();
  236.     Skip(4); // u4 compressed_size           = GetU4();
  237.     u4 uncompressed_size                     = GetU4();
  238.     u2 file_name_length                      = GetU2();
  239.     u2 extra_field_length                    = GetU2();
  240.     u2 file_comment_length                   = GetU2();
  241.     Skip(8); // u2 disk_number_start         = GetU2();
  242.              // u2 internal_file_attributes  = GetU2();
  243.              // u4 external_file_attributes  = GetU4();
  244.     u4 relative_offset_of_local_header       = GetU4();
  245.  
  246.     u4 date_time = ((u4) last_mod_file_date) << 16 | last_mod_file_time;
  247.     char *name = buffer_ptr;
  248.  
  249.     Skip(file_name_length + extra_field_length + file_comment_length);
  250.  
  251.     //
  252.     // Note that we need to process all subdirectory entries that appear in the zip file, and not
  253.     // just the ones that contain java and class files. Recall that in java the dot notation is
  254.     // used in specifying a package. Therefore, in processing a qualified-name that represents
  255.     // a package, we need to recognize each name as a subpackage. E.g., when processing
  256.     // "java.lang", we need to recognize "java" as a package before looking for "lang"...
  257.     //
  258.     if (name[file_name_length - 1] == U_SLASH)
  259.         ProcessSubdirectoryEntries(directory_symbol, name, file_name_length - 1);  // -1 to remove last '/'
  260.     else
  261.     {
  262.         bool java_file = (file_name_length >= FileSymbol::java_suffix_length &&
  263.                           FileSymbol::IsJavaSuffix(&name[file_name_length - FileSymbol::java_suffix_length])),
  264.              class_file = (file_name_length >= FileSymbol::class_suffix_length &&
  265.                            FileSymbol::IsClassSuffix(&name[file_name_length - FileSymbol::class_suf